package io.kiki.stack.netty.channelManager;

import io.kiki.stack.netty.config.ConfigManager;
import io.kiki.stack.netty.lifeCycle.AbstractLifeCycle;
import io.kiki.stack.netty.lifeCycle.LifeCycleException;
import io.kiki.stack.netty.util.NamedThreadFactory;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Slf4j
@Setter
@Getter
public class ChannelMonitor extends AbstractLifeCycle {


    private final ChannelManager channelManager;
    private final ChannelMonitorStrategy channelMonitorStrategy;

    private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;

    public ChannelMonitor(@NonNull ChannelManager channelManager, @NonNull ChannelMonitorStrategy channelMonitorStrategy) {
        this.channelMonitorStrategy = channelMonitorStrategy;
        this.channelManager = channelManager;
    }

    @Override
    public void startup() throws LifeCycleException {
        super.startup();

        /* initial delay to execute schedule task, unit: ms */
        long initialDelay = ConfigManager.conn_monitor_initial_delay();

        /* period of schedule task, unit: ms*/
        long period = ConfigManager.conn_monitor_period();

        this.scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("channelMonitorThread", true), new ThreadPoolExecutor.AbortPolicy());
        this.scheduledThreadPoolExecutor.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    Map<String, RunStateRecordedFutureTask<Pool>> connPools = null;
                    if (channelManager instanceof ChannelManagerImpl) {
                        connPools = ((ChannelManagerImpl) channelManager).getPoolKeyToRunStateRecordedFutureTaskMap();
                    }
                    channelMonitorStrategy.monitor(connPools);
                } catch (Exception e) {
                    log.warn("MonitorTask error", e);
                }
            }
        }, initialDelay, period, TimeUnit.MILLISECONDS);
    }

    @Override
    public void shutdown() throws LifeCycleException {
        super.shutdown();

        scheduledThreadPoolExecutor.purge();
        scheduledThreadPoolExecutor.shutdown();
    }


}
